#include <OgreApp.hpp>
#include <OIS.h>
using namespace DARV;

/** PUBLIC **/

OgreApp::OgreApp(void)
{
	mRoot = 0;
	mWindow = 0;
	mSceneMgr = 0;
	mCamera = 0;
	mViewport = 0;
}

OgreApp::~OgreApp(void)
{
	if (mEventListener)		delete mEventListener;
	if (mViewport)			delete mViewport;
	if (mCamera)			delete mCamera;
}

bool OgreApp::init(void)
{
	mRoot = new Ogre::Root();
	setupResources();
	if (!mRoot->showConfigDialog())
		throw "[erreur] Interruption utilisateur";
	mWindow = mRoot->initialise(true);
	loadResources();

	createSceneManager();
	createCamera();
	createViewport();
	createScene();	

	createEventListener();
	createFrameListener();

	return true;
}

void OgreApp::run(void)
{
	if (!init())
		return;

	mRoot->startRendering();
	destroyScene();
}

/*********************************************************************/

void OgreApp::createSceneManager(void)
{
	mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);
}

void OgreApp::createCamera(void)
{
	mCamera = mSceneMgr->createCamera("Camera");
	mCamera->setPosition(Ogre::Vector3(0,0,500));
	mCamera->lookAt(Ogre::Vector3(0,0,-300));
//	mCamera->setNearClipDistance(5);
}

void OgreApp::createViewport(void)
{
	mViewport = mWindow->addViewport(mCamera);
	mCamera->setAspectRatio( Ogre::Real(mViewport->getActualWidth()) / Ogre::Real(mViewport->getActualHeight()) );
}

/** PRIVATE **/

void OgreApp::setupResources(void)
{
	Ogre::ConfigFile cf;
	cf.load("resources.cfg");
	
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
	Ogre::String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator it;
		for (it = settings->begin(); it != settings->end(); it++)
		{
			typeName = it->first;
			archName = it->second;
			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
		}
	}
}

void OgreApp::loadResources(void)
{
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();  
}

void OgreApp::createFrameListener(void)
{
	Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);	
	mRoot->addFrameListener(this);
}

void OgreApp::createEventListener(void)
{
	mEventListener = new EventListener(mWindow, mCamera);
}

/**********************************************************************
 FRAME LISTENER
*/

bool OgreApp::frameStarted(const Ogre::FrameEvent& evt)
{
	if (mWindow->isClosed())
		return false;

	mEventListener->process();
	if (mEventListener->mKeyboard->isKeyDown(OIS::KC_ESCAPE))
		return false;

	return true;
}

bool OgreApp::frameEnded(const Ogre::FrameEvent& evt)
{
	return true;
}

/**********************************************************************
 WINDOW LISTENER
*/

void OgreApp::windowResized(Ogre::RenderWindow* win)
{
	unsigned int width, height, depth;
	int left, top;
	win->getMetrics(width, height, depth, left, top);


	const OIS::MouseState &ms = mEventListener->mMouse->getMouseState();
	ms.width = width;
	ms.height = height;

	std::cout << "* window resized" << std::endl;
}

void OgreApp::windowClosed(Ogre::RenderWindow* win)
{
	if (win == mWindow)
	{
		Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
	}
}
